/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2021年10月5日
 */
package com.massyframework.beanskin.guice.beancontext;

import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.google.inject.AbstractModule;
import com.google.inject.name.Names;
import com.massyframework.beanskin.assembly.Assembly;
import com.massyframework.beanskin.assembly.AssemblyConfig;
import com.massyframework.beanskin.assembly.handling.DependencyServiceProvider;
import com.massyframework.beanskin.assembly.handling.HandlerNotFoundException;
import com.massyframework.beanskin.assembly.handling.LifecycleManager;
import com.massyframework.beanskin.service.DependencyServiceDescriptor;
import com.massyframework.beanskin.service.ServiceRepository;

/**
 * 依赖模块
 * @author huangkh
 *
 */
public class DependencyModule extends AbstractModule {

	private final LifecycleManager lifecycleManager;

    /**
     * 构造方法
     * @param lifecycleManager {@link LifecycleManager}, 装配件生命周期管理器
     */
    public DependencyModule(LifecycleManager lifecycleManager){
        this.lifecycleManager = Objects.requireNonNull(
                lifecycleManager, "\"lifecycleManager\" cannot be null.");
    }


    @Override
    protected void configure() {
    	Assembly assembly = this.getAssociatedAssembly();
    	//注入assembly
    	this.bind(Assembly.class)
    		.annotatedWith(Names.named("assembly"))
    		.toInstance(assembly);
    	
    	//注入assemblyConfig
    	this.bind(AssemblyConfig.class)
    		.annotatedWith(Names.named("assemblyConfig"))
    		.toInstance(assembly.getConfig());
    	
    	//注入ServiceRepository
    	ServiceRepository repo = ServiceRepository.retrieveFrom(assembly);
    	this.bind(ServiceRepository.class)
    		.annotatedWith(Names.named("serviceRepository"))
    		.toInstance(repo);
    	
        DependencyServiceProvider handler = findHandler(DependencyServiceProvider.class);
        if (handler != null) {
            Map<DependencyServiceDescriptor<?>, Object> dependencyServices =
                    handler.getDependencyServices();
            for (Map.Entry<DependencyServiceDescriptor<?>, Object> entry: dependencyServices.entrySet()) {
            	DependencyServiceDescriptor<?> descriptor = entry.getKey();
                Object service = entry.getValue();
                this.doAddDependencyService(descriptor, service);
            }
        }

    }

    /**
     * 执行添加依赖服务
     * @param descriptor 依赖服务描述
     * @param service 服务
     */
    @SuppressWarnings("unchecked")
    private <T> void doAddDependencyService(DependencyServiceDescriptor<T> descriptor, Object service){
        if (descriptor.getBeanName() == null){
            this.bind(descriptor.getRequiredType()).toInstance((T)service);
        }else{
            this.bind(descriptor.getRequiredType())
                    .annotatedWith(Names.named(descriptor.getBeanName()))
                    .toInstance((T)service);
        }
    }

    /**
     * 查找<code>handlerType</code>类型的处理器实例
     * @param handlerType {@link Class}, 处理器类型
     * @param <T>
     * @return {@link T}, 可能返回null.
     */
    protected <T> T findHandler(Class<T> handlerType){
        LifecycleManager lifecycleManager = this.getLifecycleManager();
        return lifecycleManager.findHandler(handlerType);
    }

    /**
     * 获取<code>handlerType</code>类型的处理器实例
     * @param handlerType {@link Class}, 处理器类型
     * @param <T>
     * @return {@link T}
     * @throws HandlerNotFoundException 未找到符合要求处理器实例抛出例外
     */
    protected <T> T getHandler(Class<T> handlerType) throws HandlerNotFoundException {
        LifecycleManager lifecycleManager = this.getLifecycleManager();
        return lifecycleManager.getHandler(handlerType);
    }

    /**
     * 所有实现<code>handlerType</code>的处理器实例
     * @param handlerType {@link Class}, 处理器类型
     * @param <T>
     * @return {@link List}
     */
    protected <T> List<T> getHandlers(Class<T> handlerType){
        LifecycleManager lifecycleManager = this.getLifecycleManager();
        return lifecycleManager.getHandlers(handlerType);
    }
    /**
     * 关联的装配件
     * @return {@link Assembly}
     */
    protected Assembly getAssociatedAssembly(){
        LifecycleManager lifecycleManager = this.getLifecycleManager();
        return lifecycleManager.getAssociatedAssembly();
    }

    /**
     * 生命周期管理器
     * @return {@link LifecycleManager}
     */
    protected LifecycleManager getLifecycleManager(){
        return this.lifecycleManager;
    }


}
